package com.sudo.boot.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class ChatServer {
    public static void main(String[] args) throws IOException {
        // 创建ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 设置端口
        serverSocketChannel.socket().bind(new InetSocketAddress(8888));
        // 设置非阻塞
        serverSocketChannel.configureBlocking(false);
        // 得到selector
        Selector selector = Selector.open();
        // 注册channel到selector上，
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("聊天室启动成功");

        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();

                // 判断是否为客户端连接进来
                if (key.isAcceptable()) {
                    // 处理客户端连接
                    handleAccept(key);
                }

                // 判断客户端是否有数据进来
                if (key.isReadable()) {
                    // 处理客户端发送过来的消息
                    handleRead(key);
                }
                if (key.isWritable()) {


                }
                iterator.remove();
            }
        }
    }

    /**
     * 获取客户端发过来的数据，并且广播给其他客户端
     */
    private static void handleRead(SelectionKey key) throws IOException {
         SocketChannel socketChannel = (SocketChannel) key.channel();
         ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        Selector selector = key.selector();
        StringBuilder message = new StringBuilder();
        while (socketChannel.read(byteBuffer) > 0) {
            byteBuffer.flip();
            message.append(new String(byteBuffer.array(), 0, byteBuffer.limit(), StandardCharsets.UTF_8));
            byteBuffer.clear();
        }
        // 将消息广播给其他客户端
        if (!message.isEmpty()) {
            // 服务端本地打印
            System.out.println(socketChannel.getRemoteAddress() + "=" + message);
            handleMessage(message.toString(), key);
        }
        // 将channel再次注册到selector上，让selector对read操作感兴趣
        socketChannel.register(selector, SelectionKey.OP_READ);
    }

    /**
     * 广播消息给其他客户端
     */
    private static void handleMessage(String message, SelectionKey key) throws IOException {
        Selector selector = key.selector();
        // 获取所有客户端
        Set<SelectionKey> keys = selector.keys();
        // 遍历
        for (SelectionKey clientKey : keys) {
            SelectableChannel channel = clientKey.channel();
            // 不发给自己
            if (channel instanceof SocketChannel socketChannel && channel != key.channel()) {
                socketChannel.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)));
            }
        }
    }

    private static void handleAccept(SelectionKey key) throws IOException {
        // ServerSocketChannel
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
        Selector selector = key.selector();
        SocketChannel socketChannel = serverSocketChannel.accept();
        // 设置非阻塞
        socketChannel.configureBlocking(false);
        // 对socketChannel的读操作感兴趣
        socketChannel.register(selector, SelectionKey.OP_READ);

        // 向客户端发送一条提示语
        socketChannel.write(ByteBuffer.wrap("欢迎加入".getBytes()));
    }
}
